/*
		动态内存管理

		夏思成

		2024年4月13日

		西科大15号公寓楼
*/

//我们现在已有的内存开辟方式：

//int a = 10;//在栈上开辟四个字节的空间
//int arr[10] = { 0 };//在栈上开辟40个字节的连续空间


//利用malloc函数开辟空间

//#include <stdio.h>
//#include <stdlib.h>
//
//int main()
//{
//	//开辟了一个40个字节的内存大小
//	int* p = (int*)malloc(sizeof(int) * 10);
//	printf("%p\n", p);
//
//	//使用free函数，释放该内存空间
//	free(p);
//	printf("%p\n", p);
//
//	return 0;
//}


//
//#include <stdio.h>
//#include <stdlib.h>
//
//int main()
//{
//	//开辟了一个40个字节的内存大小
//	int* p = (int*)malloc(sizeof(int) * 10);
//	printf("%p\n", p);
//
//	//对所申请的空间进行检查，如果为NULL，则申请失败，终止程序
//	if (p == NULL)
//	{
//		perror("malloc");
//		return 1;
//	}
//
//	//利用该空间存放1~10
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		p[i] = i + 1;
//	}
//
//	//使用free函数，释放该内存空间
//	free(p);
//	printf("%p\n", p);
//	p = NULL;//为避免野指针，将p置为NULL
//	return 0;
//}


////利用calloc函数动态开辟内存
//
//#include <stdio.h>
//#include <stdlib.h>
//#include <assert.h>
//
//int main()
//{
//	//为5个整型开辟空间
//	int* pm = (int*)malloc(sizeof(int) * 5);
//	int* pc = (int*)calloc(5, sizeof(int));
//
//	//对申请的地址进行检查，如果为NULL指针，则开辟失败，终止程序
//	assert(pm);
//	if (pc == NULL)
//	{
//		perror("calloc");
//		return 1;
//	}
//
//	int i = 0;
//	for (i = 0; i < 5; i++)
//	{
//		printf("%d ", *(pm + i));
//		printf("%d ", *(pc + i));
//	}
//
//	//使用完后释放该内存空间，并将其指针置为空指针
//	free(pc);
//	pc = NULL;
//	return 0;
//}

//
//#include <stdio.h>
//#include <stdlib.h>
//
//int main()
//{
//	//为5个整型开辟空间
//	int* p = (int*)calloc(5, sizeof(int));
//
//	//对申请的地址进行检查，如果为NULL指针，则开辟失败，终止程序
//	if (p == NULL)
//	{
//		perror("calloc");
//		return 1;
//	}
//
//	//calloc会将创建的空间的每个字节初始化为0
//	int i = 0;
//	for (i = 0; i < 5; i++)
//	{
//		printf("%d ", *(p + i));
//	}
//
//	//使用完后释放该内存空间，并将其指针置为空指针
//	free(p);
//	p = NULL;
//	return 0;
//}


////利用realloc函数进行内存大小的修改
//
//#include <stdio.h>
//#include <stdlib.h>
//
//int main()
//{
//	//创建5个整形大小的内存——20字节
//	int* p = (int*)malloc(sizeof(int) * 5);
//
//	//……
//
//	//将原来申请的空间扩大为40字节
//	int* ptr = realloc(p, sizeof(int) * 10);
//
//	return 0;
//}





//#include <stdio.h>
//#include <stdlib.h>
//
//int main()
//{
//	int* p = (int*)malloc(sizeof(int) * 5);
//	if (p == NULL)
//	{
//		perror("malloc");
//		return 1;
//	}
//
//	int *ptr = realloc(p, sizeof(int) * 10);
//
//	if (ptr != NULL)//开辟成功
//	{
//		p = ptr;
//		ptr = NULL;
//		//...
//	}
//	else//开辟失败，可以继续使用原来的空间
//	{
//		//...
//	}
//	return 0;
//}

////realloc的特殊用法
//
//#include <stdio.h>
//#include <stdlib.h>
//
//int main()
//{
//	int* p = realloc(NULL, sizeof(int) * 5);
//	//上式 == malloc(sizeof(int)*5);
//
//	return 0;
//}

//4.1对NULL的解引用操作
//
//#include <stdio.h>
//#include <stdlib.h>
//
//int main()
//{
//	int* p = (int*)malloc(10*INT_MAX);
//
//	*p = 20;
//	free(p);
//	p = NULL;
//
//	return 0;
//}

//4.2对动态开辟空间的越界访问
//
//#include <stdio.h>
//#include <stdlib.h>
//
//int main()
//{
//	int* p = (int*)malloc(sizeof(int) * 5);
//	if (p == NULL)
//	{
//		perror("malloc");
//		return 1;
//	}
//	
//	int i = 0;
//	for (i = 0; i <= 5; i++)
//	{
//		*(p + i) = i + 1;
//	}
//
//	free(p);
//	p = NULL;
//	return 0;
//}
//



////4.3对非动态开辟内存使用free
//
//#include <stdio.h>
//#include <stdlib.h>
//
//int main()
//{
//	int n = 20;
//	int* p = &n;
//	free(p);
//	p = NULL;
//	return 0;
//}




////4.4使用free释放动态开辟内存的一部分
//
//#include <stdio.h>
//#include <stdlib.h>
//
//void test()
//{
//	int* p = (int*)malloc(100);
//	p++;
//	free(p);//p不再指向动态内存的起始位置 
//}
//
//int main()
//{
//	test();
//	return 0;
//}



////4.5对同一块动态内存多次释放
//
//#include <stdio.h>
//#include <stdlib.h>
//
//void test()
//{
//	int* p = (int*)malloc(100);
//	free(p);
//	free(p);//重复释放 
//}
//
//int main()
//{
//	test();
//	return 0;
//}

//
////4.6动态开辟内存忘记释放（内存泄露）
//
//#include <stdio.h>
//#include <stdlib.h>
//
//void test()
//{
//	int* p = (int*)malloc(100);
//	if (NULL != p)
//	{
//		*p = 20;
//	}
//}
//
//int main()
//{
//	test();
//
//	while (1);
//}


/*
		使用malloc函数模拟开辟一个3*5的整型二维数组，开辟好后，使用二维数组的下标访问形式，访问空间。
*/


#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

int main()
{
	//开辟三个一维数组
	int* col1 = (int*)malloc(sizeof(int) * 5);
	int* col2 = (int*)malloc(sizeof(int) * 5);
	int* col3 = (int*)malloc(sizeof(int) * 5);
	if (col1 == NULL || col2 == NULL || col3 == NULL)
	{
		perror("malloc");
		return 1;
	}

	int** arr = (int**)malloc(sizeof(int*) * 3);
	assert(arr);
	arr[0] = col1;
	arr[1] = col2;
	arr[2] = col3;

	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			arr[i][j] = j + 1;
		}
	}

	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}


	for (i = 0; i < 3; i++)
	{
		free(arr[i]);
		arr[i] = NULL;
	}
	free(arr);
	arr = NULL;
	return 0;
}